package org.luxor.commons.core.config;

import org.luxor.commons.core.config.properties.ThreadPoolProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

import javax.annotation.Resource;
import java.lang.reflect.Method;

@EnableAsync
@Configuration
@EnableConfigurationProperties({ThreadPoolProperties.class})
public class ThreadPoolConfig extends AsyncConfigurerSupport {
    private static final Logger logger = LoggerFactory.getLogger(ThreadPoolConfig.class);

    private static final String THREAD_POOL_NAME_PREFIX = "Spring-Thread-";
    private static final String ASYNC_THREAD_NAME_PREFIX = "Async-Thread-";
    private static final String SCHEDULED_THREAD_NAME_PREFIX = "Scheduled-Thread-";

    @Resource
    private ThreadPoolProperties threadPoolProperties;

    /**
     * Async 异步线程池
     */
    @Override
    public ThreadPoolTaskExecutor getAsyncExecutor() {
        /**
         *   默认情况下，在创建了线程池后，线程池中的线程数为0，当有任务来之后，就会创建一个线程去执行任务，
         *	当线程池中的线程数目达到corePoolSize后，就会把到达的任务放到缓存队列当中；
         *  当队列满了，就继续创建线程，当线程数量大于等于maxPoolSize后，开始使用拒绝策略拒绝
         */
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 当前线程数
        executor.setCorePoolSize(threadPoolProperties.getCorePoolSize());
        // 最大线程数
        executor.setMaxPoolSize(threadPoolProperties.getMaxPoolSize());
        // 线程池所使用的缓冲队列
        executor.setQueueCapacity(threadPoolProperties.getQueueCapacity());
        // 允许线程空闲时间（单位：默认为秒）
        executor.setKeepAliveSeconds(threadPoolProperties.getKeepAliveSeconds());
        // 等待所有线程执行完再销毁线程池
        executor.setWaitForTasksToCompleteOnShutdown(threadPoolProperties.isWaitForJobsToCompleteOnShutdown());
        // 最长等待多久再销毁线程池
        executor.setAwaitTerminationSeconds(threadPoolProperties.getAwaitTerminationSeconds());
        // 线程名称前缀
        executor.setThreadNamePrefix(ASYNC_THREAD_NAME_PREFIX);
        // 拒绝策略(无线程可用时的处理策略)
        executor.setRejectedExecutionHandler(threadPoolProperties.getRejectedExecutionHandler());
        // 初始化
        executor.initialize();
        return executor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (Throwable ex, Method method, Object... params) -> {
            if (logger.isErrorEnabled()) {
                logger.error("Unexpected error occurred invoking async method: {}", method, ex);
            }
        };
    }

    /**
     * Scheduled 默认线程池
     */
    @Bean
    @ConditionalOnMissingBean(name = "scheduledExecutorService")
    public TaskScheduler scheduledExecutorService(ThreadPoolProperties threadPoolProperties) {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        // 核心线程数
        scheduler.setPoolSize(threadPoolProperties.getCorePoolSize());
        // 等待所有线程执行完再销毁线程池
        scheduler.setWaitForTasksToCompleteOnShutdown(threadPoolProperties.isWaitForJobsToCompleteOnShutdown());
        // 最长等待多久再销毁线程池
        scheduler.setAwaitTerminationSeconds(threadPoolProperties.getAwaitTerminationSeconds());
        // 线程名称前缀
        scheduler.setThreadNamePrefix(SCHEDULED_THREAD_NAME_PREFIX);
        // 拒绝策略(无线程可用时的处理策略)
        scheduler.setRejectedExecutionHandler(threadPoolProperties.getRejectedExecutionHandler());
        return scheduler;
    }

    @Bean
    @Order(-1)
    @ConditionalOnMissingBean(name = "threadPoolTaskExecutor")
    public TaskExecutor threadPoolTaskExecutor(ThreadPoolProperties threadPoolProperties) {
        /**
         *   默认情况下，在创建了线程池后，线程池中的线程数为0，当有任务来之后，就会创建一个线程去执行任务，
         *	当线程池中的线程数目达到corePoolSize后，就会把到达的任务放到缓存队列当中；
         *  当队列满了，就继续创建线程，当线程数量大于等于maxPoolSize后，开始使用拒绝策略拒绝
         */
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 当前线程数
        executor.setCorePoolSize(threadPoolProperties.getCorePoolSize());
        // 最大线程数
        executor.setMaxPoolSize(threadPoolProperties.getMaxPoolSize());
        // 线程池所使用的缓冲队列
        executor.setQueueCapacity(threadPoolProperties.getQueueCapacity());
        // 允许线程空闲时间（单位：默认为秒）
        executor.setKeepAliveSeconds(threadPoolProperties.getKeepAliveSeconds());
        // 等待所有线程执行完再销毁线程池
        executor.setWaitForTasksToCompleteOnShutdown(threadPoolProperties.isWaitForJobsToCompleteOnShutdown());
        // 最长等待多久再销毁线程池
        executor.setAwaitTerminationSeconds(threadPoolProperties.getAwaitTerminationSeconds());
        // 线程名称前缀
        executor.setThreadNamePrefix(THREAD_POOL_NAME_PREFIX);
        // 拒绝策略(无线程可用时的处理策略)
        executor.setRejectedExecutionHandler(threadPoolProperties.getRejectedExecutionHandler());
        // 初始化
        executor.initialize();
        return executor;
    }
}
